package com.ruoyi.tzai.service.impl;

import org.dromara.x.file.storage.core.FileInfo;
import org.dromara.x.file.storage.core.FileStorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.tzai.service.IFileUploadService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;

import java.io.InputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * 文件上传服务实现
 * 使用 x-file-storage 上传到阿里云 OSS
 * 
 * @author tzai
 * @date 2025-10-28
 */
@Service
public class FileUploadServiceImpl implements IFileUploadService 
{
    private static final Logger log = LoggerFactory.getLogger(FileUploadServiceImpl.class);
    
    @Autowired
    private FileStorageService fileStorageService;
    
    // 阿里云OSS配置
    @Value("${dromara.x-file-storage.aliyun-oss[0].access-key}")
    private String ossAccessKey;
    
    @Value("${dromara.x-file-storage.aliyun-oss[0].secret-key}")
    private String ossSecretKey;
    
    @Value("${dromara.x-file-storage.aliyun-oss[0].end-point}")
    private String ossEndpoint;
    
    @Value("${dromara.x-file-storage.aliyun-oss[0].bucket-name}")
    private String ossBucketName;
    
    /**
     * 生成带日期路径的目录
     * 格式: image/2025/11/03/
     */
    private String generatePath(String type) {
        LocalDate now = LocalDate.now();
        String datePath = now.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
        return String.format("%s/%s/", type, datePath);
    }

    @Override
    public FileInfo uploadAudio(InputStream inputStream, String fileName, long fileSize) {
        try {
            log.info("开始上传音频文件: {}, 大小: {} bytes", fileName, fileSize);
            
            // 生成存储路径（只包含目录，文件名由x-file-storage自动生成）
            String path = generatePath("audio");
            
            // 上传文件
            FileInfo fileInfo = fileStorageService.of(inputStream)
                    .setPath(path)
                    .setOriginalFilename(fileName)
                    .setPlatform("aliyun-oss")  // 指定使用阿里云OSS
                    .upload();
            
            log.info("音频文件上传成功: {} (URL: {})", fileInfo.getFilename(), fileInfo.getUrl());
            return fileInfo;  // 返回完整的 FileInfo 对象
            
        } catch (Exception e) {
            log.error("音频文件上传失败", e);
            return null;
        }
    }

    @Override
    public FileInfo uploadImage(InputStream inputStream, String fileName, long fileSize) {
        try {
            log.info("开始上传图片文件: {}, 大小: {} bytes", fileName, fileSize);
            
            // 生成存储路径（只包含目录）
            String path = generatePath("image");
            
            // 上传文件
            FileInfo fileInfo = fileStorageService.of(inputStream)
                    .setPath(path)
                    .setOriginalFilename(fileName)
                    .setPlatform("aliyun-oss")
                    .upload();
            
            log.info("图片文件上传成功: {} (URL: {})", fileInfo.getFilename(), fileInfo.getUrl());
            return fileInfo;  // 返回完整的 FileInfo 对象
            
        } catch (Exception e) {
            log.error("图片文件上传失败", e);
            return null;
        }
    }
    
    @Override
    public FileInfo uploadFile(MultipartFile file, String fileType) {
        try {
            log.info("开始上传文件: {}, 类型: {}, 大小: {} bytes", 
                    file.getOriginalFilename(), fileType, file.getSize());
            
            // 生成存储路径（只包含目录）
            String path = generatePath(fileType);
            
            // 上传文件
            FileInfo fileInfo = fileStorageService.of(file)
                    .setPath(path)
                    .setPlatform("aliyun-oss")
                    .upload();
            
            log.info("文件上传成功: {} (URL: {})", fileInfo.getFilename(), fileInfo.getUrl());
            return fileInfo;
            
        } catch (Exception e) {
            log.error("文件上传失败: {}", file.getOriginalFilename(), e);
            return null;
        }
    }
    
    @Override
    public byte[] downloadFile(FileInfo fileInfo) {
        try {
            log.info("开始下载文件: {}", fileInfo.getFilename());
            
            // 使用 x-file-storage 下载文件
            byte[] fileBytes = fileStorageService.download(fileInfo).bytes();
            
            log.info("文件下载成功: {}, 大小: {} bytes", fileInfo.getFilename(), fileBytes.length);
            return fileBytes;
            
        } catch (Exception e) {
            log.error("文件下载失败: {}", fileInfo.getFilename(), e);
            return null;
        }
    }

    @Override
    public boolean deleteFile(String fileUrl) {
        try {
            log.info("开始删除文件: {}", fileUrl);
            
            // 通过 URL 删除文件
            boolean result = fileStorageService.delete(fileUrl);
            
            if (result) {
                log.info("文件删除成功: {}", fileUrl);
            } else {
                log.warn("文件删除失败: {}", fileUrl);
            }
            
            return result;
            
        } catch (Exception e) {
            log.error("文件删除异常: {}", fileUrl, e);
            return false;
        }
    }
    
    @Override
    public String generateSignedUrl(FileInfo fileInfo, int expireMinutes) {
        OSS ossClient = null;
        try {
            log.info("开始生成签名URL: {}, 过期时间: {}分钟", fileInfo.getFilename(), expireMinutes);
            
            // 创建OSS客户端
            ossClient = new OSSClientBuilder().build(ossEndpoint, ossAccessKey, ossSecretKey);
            
            // 从FileInfo中获取文件路径（basePath + path + filename）
            String objectName = fileInfo.getBasePath() + fileInfo.getPath() + fileInfo.getFilename();
            
            // 设置过期时间
            Date expiration = new Date(System.currentTimeMillis() + expireMinutes * 60 * 1000L);
            
            // 生成签名URL请求
            GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(ossBucketName, objectName);
            request.setExpiration(expiration);
            
            // 生成签名URL
            java.net.URL signedUrl = ossClient.generatePresignedUrl(request);
            String urlString = signedUrl.toString();
            
            // 强制使用HTTPS协议（iOS要求）
            if (urlString.startsWith("http://")) {
                urlString = urlString.replace("http://", "https://");
                log.info("已转换为HTTPS: {}", urlString);
            }
            
            log.info("签名URL生成成功: {}", urlString);
            return urlString;
            
        } catch (Exception e) {
            log.error("生成签名URL失败: {}", fileInfo.getFilename(), e);
            // 如果生成签名URL失败，返回原始URL（公开访问）
            String url = fileInfo.getUrl();
            // 确保返回的URL也是HTTPS
            if (url != null && url.startsWith("http://")) {
                url = url.replace("http://", "https://");
            }
            return url;
        } finally {
            // 关闭OSS客户端
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    @Override
    public String uploadAudioToOSS(byte[] audioData, String ossKey) {
        try {
            log.info("开始上传音频到OSS: {}, 大小: {} bytes", ossKey, audioData.length);
            
            // 使用 ByteArrayInputStream
            java.io.ByteArrayInputStream inputStream = new java.io.ByteArrayInputStream(audioData);
            
            // 分解 ossKey 获取文件名
            String fileName = ossKey.substring(ossKey.lastIndexOf('/') + 1);
            
            // 上传文件，直接指定完整路径
            FileInfo fileInfo = fileStorageService.of(inputStream)
                    .setPath("")  // 空路径，完整路径由 setSaveFilename 指定
                    .setSaveFilename(ossKey)  // 完整路径
                    .setOriginalFilename(fileName)
                    .setPlatform("aliyun-oss")
                    .upload();
            
            String url = fileInfo.getUrl();
            
            // 确保使用HTTPS
            if (url != null && url.startsWith("http://")) {
                url = url.replace("http://", "https://");
            }
            
            log.info("音频上传成功: {}", url);
            return url;
            
        } catch (Exception e) {
            log.error("音频上传到OSS失败: ossKey={}", ossKey, e);
            throw new RuntimeException("音频上传失败: " + e.getMessage(), e);
        }
    }
}

